package xtime

import (
	"database/sql/driver"
	"errors"
	"fmt"
	"time"
)

type Date time.Time

func (t Date) Ptr() *Date {
	return &t
}

// Scan 实现 sql.Scanner 接口，处理从数据库里拿出的值
func (t *Date) Scan(value interface{}) error {
	switch vt := value.(type) {
	case string:
		tTime, err := time.ParseInLocation(DateFormatLineV3, vt, time.Local)
		if err != nil {
			return err
		}
		*t = Date(tTime)
	case time.Time:
		*t = Date(vt)
		return nil
	}

	return fmt.Errorf("scan value type err")
}

// Value 实现 driver.Valuer 接口，处理将要写入数据库的值
func (t Date) Value() (driver.Value, error) {
	if t.Time().IsZero() {
		return nil, nil
	}
	return time.Time(t), nil
}

// Time get time.
func (t Date) Time() time.Time {
	return time.Time(t)
}

func (t *Date) UnmarshalJSON(data []byte) error {
	if string(data) == "null" {
		return nil
	}
	// TODO(https://go.dev/issue/47353): Properly unescape a JSON string.
	if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
		return errors.New("Time.UnmarshalJSON: input is not a JSON string")
	}

	var now time.Time
	var err error

	if now, err = time.ParseInLocation(`"`+DateFormatLineV3+`"`, string(data), time.Local); err == nil {
		*t = Date(now)
		return nil
	}

	if now, err = time.ParseInLocation(`"`+DateYmdFormatLine+`"`, string(data), time.Local); err == nil {
		*t = Date(now)
		return nil
	}

	if now, err = time.ParseInLocation(`"`+DateYmdNoLine+`"`, string(data), time.Local); err == nil {
		*t = Date(now)
		return nil
	}

	return err
}

func (t Date) MarshalJSON() ([]byte, error) {
	if t.Time().IsZero() {
		return []byte{'"', '"'}, nil
	}

	b := make([]byte, 0, len(DateFormatLineV3)+2)
	b = append(b, '"')
	b = time.Time(t).AppendFormat(b, DateFormatLineV3)
	b = append(b, '"')
	return b, nil
}

func (t Date) String() string {
	if t.Time().IsZero() {
		return ""
	}
	return time.Time(t).Format(DateFormatLineV3)
}

func (t Date) GormDataType() string {
	return "date"
}
